/***************************************************************************
 *	@file 		fetion_login.h
 *	@Author 	baoyu0125@gmail.com
 *	@create		2011-7
 *	@version 	1.0.0
 *	@brief		definition of class loginThreadCallable, class SSLclient and 
 *				class HashPassword, loginThreadCallable is for login thread
 *				function object, SSLclient is about SSL socket, HashPassword 
 *				is hash password generator
 *	@modify		none
 ***************************************************************************/

#ifndef FETION_LOGIN_H
#define FETION_LOGIN_H

using boost::asio::ip::tcp;
//using boost::asio::ssl;

class loginThreadCallable
{
public:
	loginThreadCallable(const std::string &no, const std::string &passwd, const int state)
		: login_no(no), login_passwd(passwd), login_state(state) {}
	int operator() () { return login_action(); }

private:
	int login_action();
	
	int SSI_auth_action(Glib::ustring &ssi_res) const;
	int parse_ssi_response(const std::string &ssi_res) const;

	int input_verify_code() const;

	int download_configuration(Glib::ustring &config_res) const;

	int sipc_reg_action(std::string &sipc_res) const;
	int parse_sipc_reg_response(const std::string sipres, 
		std::string &nonce, std::string &key) const;

	int generate_sip_response(const std::string &nonce,
		const std::string publickey, const char* aeskey, std::string &response) const;

	std::string generate_cnonce() const;
	char* generate_aes_key() const;

	int sipc_auth_action(std::string &sip_res, const std::string &response) const;
	int parse_sipc_auth_response(const std::string &sip_res) const;

	int contact_subscribe_only() const;
	std::string generate_subscribe_body(const std::string version) const;

private:
	std::string login_no;
	std::string login_passwd;
	int			login_state;
};

class SSLclient
{
public:
	SSLclient(boost::asio::io_service &io_service_ssl, boost::asio::ssl::context &ctx,
		tcp::resolver::iterator endpoint_iterator);
	int get_ssi_response(const std::string request, Glib::ustring &response);

private:
	boost::asio::ssl::stream<tcp::socket> ssl_sock;
};

class HashPassword
{
public:
	HashPassword(const std::string &id, const std::string &passwd) 
		: login_userId(id), login_passwd(passwd) { }
	std::string get_password();

private:
	std::string hash_password_v1(const unsigned char* b0 , 
		int b0len , const unsigned char* password , int psdlen);
	std::string hash_password_v2(const std::string userid, const std::string passwordhex);
	
	std::string login_userId;
	std::string login_passwd;
};

class Register
{
public:
	Register(boost::asio::io_service &io, int secs0) : 
		timer_(io, boost::posix_time::seconds(60)), secs(secs0) 
	{
		timer_.async_wait(boost::bind(&Register::keep_alive, 
			this, boost::asio::placeholders::error));
	}
private:
	void keep_alive(const boost::system::error_code& error);
	std::string generate_keep_alive_body();
private:
	boost::asio::deadline_timer timer_;
	int secs;
};


#endif
